package com.atguigu.userprofile.utils;

import com.atguigu.userprofile.beans.TagInfo;
import com.atguigu.userprofile.constant.ConstCode;
import com.google.common.base.CaseFormat;
import org.apache.commons.beanutils.BeanUtils;

import java.sql.*;
import java.util.ArrayList;
import java.util.List;

/**
 * @Classname MySQLUtil
 * @Date 2022/10/2 13:52
 * @Created by arun
 * <p>
 * 完成基于Mysql的CRUD操作
 */
public class MySQLUtil {

    static String url = MyPropsUtil.get(ConstCode.MYSQL_URL);
    static String username = MyPropsUtil.get(ConstCode.MYSQL_USERNAME);
    static String password = MyPropsUtil.get(ConstCode.MYSQL_PASSWORD);

    public static <T> T selectOne(String sql, Class<T> cls, boolean isUnderScoreToCamel) {

        List<T> tList = selectList(sql, cls, isUnderScoreToCamel);
        if (!tList.isEmpty()) {
            return tList.get(0);
        } else {
            return null;
        }
    }

    /**
     * JDBC步骤：
     * 1、注册驱动
     * 2、获取连接
     * 3、编写sql
     * 4、预编译sql
     * 5、设置参数
     * 6、执行sql
     * 7、处理结果集
     * 8、关闭连接
     *
     * @param sql                 执行哪条sql
     * @param cls                 结果封装成什么类型的对象
     * @param isUnderScoreToCamel 是否下划线转驼峰
     * @param <T>
     * @return
     */
    public static <T> List<T> selectList(String sql, Class<T> cls, boolean isUnderScoreToCamel) {

        Connection conn = null;
        PreparedStatement prepareStatement = null;
        ResultSet resultSet = null;

        ArrayList<T> tList = new ArrayList<>();

        try {
            // 1、注册驱动
            Class.forName("com.mysql.jdbc.Driver");
            // 2、获取连接
            conn = DriverManager.getConnection(url, username, password);
            // 3、编写sql
            // 4、预编译sql
            prepareStatement = conn.prepareStatement(sql);
            // 5、设置参数
            // 6、执行sql
            resultSet = prepareStatement.executeQuery();
            // 7、处理结果集
            /**
             * 这时候我们还不知道sql是啥，我们不知道sql查出来的是什么东西，那怎么处理结果集？
             * 如果用Object，我们 .getObject(int columnIndex)，都不知道有几列，把列的数据给谁
             * TODO 所以我们要想办法知道查到的东西到底是什么
             */
            // 得到数据集的列信息
            ResultSetMetaData metaData = resultSet.getMetaData();
            int columnCount = metaData.getColumnCount();
            while (resultSet.next()) {
                // 每条数据封装成一个T对象
                T obj = cls.newInstance();
                // TODO JDBC里的下标是从1开始的
                for (int i = 1; i <= columnCount; i++) {
                    //String columnName = metaData.getColumnName(i);
                    //TODO 考虑到sql中可能会取别名，不建议用getColumnName()
                    String columnName = metaData.getColumnLabel(i);
                    Object columnValue = resultSet.getObject(columnName);

                    //obj.set()
                    //这时候不知道obj是什么，没法调用set()
                    //BeanUtils.copyProperty(obj,,columnValue);
                    //TODO 要填写对象的属性的名字，但是mysql中用下划线_，JavaBean是驼峰，怎么解决冲突？
                    String objFieldName = null;
                    if (isUnderScoreToCamel) {
                        // tag_code => tagCode
                        objFieldName = CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, columnName);
                    } else {
                        objFieldName = columnName;
                    }

                    // 设置到对象属性上
                    BeanUtils.copyProperty(obj, objFieldName, columnValue);
                }
                // 将当前对象添加到集合中
                tList.add(obj);
            }
            // 将对象返回
            return tList;
        } catch (Exception e) {
            //e.printStackTrace();
            throw new RuntimeException("查询mysql失败...");
        } finally {
            try {
                resultSet.close();
                prepareStatement.close();
                conn.close();
            } catch (SQLException throwables) {
                //throwables.printStackTrace();
                throw new RuntimeException("关闭资源失败...");
            }
        }
    }

    public static void main(String[] args) {
        String sql = "select * from tag_info where id = 7";
        TagInfo tagInfo = selectOne(sql, TagInfo.class, true);
        System.out.println(tagInfo);
    }
}
